#include "PluginManager.h"

#include <loong/Logger.h>

#include <dlfcn.h>
#include <fstream>


typedef void *(*createPluginObject)();
PluginManager* PluginManager::m_instance = NULL;
PluginManager::PluginManager()
{
	m_instance = this;
}

PluginManager* PluginManager::getInstance()
{
	return m_instance;
}

bool PluginManager::loadPlugins()
{
	DEBUG("%s", __FUNCTION__);

	std::string soCfgFile("./plugin.conf");
	
	std::ifstream file(soCfgFile);
	if (!file.is_open())
	{
		ERROR("open config file %s failed!\n", soCfgFile.c_str());
		return false;
	}

	while (!file.eof())
	{
		std::string buf;
		file >> buf;

		if (buf == "soname")
		{
			buf.clear();
			file >> buf;
			void *handle = dlopen(buf.c_str(), RTLD_LAZY);

			if (nullptr == handle)
			{
				ERROR("failed to open %s, error: %s\n", buf.c_str(), dlerror());
				return false;
			}

			INFO("load dynamic library %s success\n", buf.c_str());

			// reset errors
			dlerror();
			createPluginObject createObject =
				(createPluginObject)dlsym(handle, "CreatePluginInstance");
			const char* err = dlerror();

			if (err != nullptr)
			{
				ERROR("failed to load creator, error: %s", err);
				return false;
			}

			// reset errors
			dlerror();
			IPlugin *pluginObject = (IPlugin *)(*createObject)();
			
			pluginObject->initPlugin();
			
			std::string pluginName = pluginObject->getName();
			char buf[512] = { 0 };
			snprintf(buf, 512, "load plugin:%s ", pluginName.c_str());
			INFO("%s", buf);
	
			m_pluginMap[pluginObject->getCmdCode()] = pluginObject;
		}
	}

	return true;
}

void PluginManager::dispatch(std::shared_ptr<Msg> msg)
{
	DEBUG("%s", __FUNCTION__);
	auto it = m_pluginMap.find(msg->cmdCode);
	if (it != m_pluginMap.end())
	{
		IPlugin *ptrPlugin = it->second;
		ptrPlugin->dispatch(msg);
	}
}

PluginManager::~PluginManager()
{
}
